home *** CD-ROM | disk | FTP | other *** search
/ Ian & Stuart's Australian Mac 1993 September / September 93.iso / Archives / Sound / MIDI / MIDI Utilities / CMU Midi Toolkit / Source / phase1.c < prev    next >
Text File  |  1987-02-12  |  39KB  |  1,365 lines

  1. /* phase1.c
  2.  *
  3.  * phase1 parses an adagio input stream and builds a linked list structure
  4.  * consisting of notes and control changes in time order
  5.  */
  6.  
  7. /*****************************************************************************
  8. *        Change Log
  9. *  Date        | Change
  10. *-----------+-----------------------------------------------------------------
  11. * 31-Dec-85 | Created changelog
  12. * 31-Dec-85 | Added standard command scanner, metronome variable, need to add
  13. *            |  cmdline_help procedure
  14. *  1-Jan-86 | Put error messages out to stderr
  15. * 18-Jan-86 | Shortened durations by 1/200 s to avoid roundoff problems --
  16. *            |  see buildnote for details
  17. *  3-Mar-86 | Allow octave and accidentals in either order after pitch name
  18. *            | Default octave is now one that gets nearest previous pitch,
  19. *            |  the tritone (half an octave) interval is descending by default
  20. *            | Special commands handled by table search
  21. *            | !Rate command added to scale all times by a percentage
  22. *            |  (50 = half speed)
  23. * 12-Mar-86 | Broke off command line parser into adagio.c, only parser remains
  24. * 24-Mar-86 | Changed representation from note_struct to event_struct
  25. *            | Parse M, N, O, X, and Y as control change commands
  26. * 23-May-86 | Added , and ; syntax: "," means "N0\n", ";" means "\n"
  27. * 16-Jul-86 | Modify to only call toupper/lower with upper/lower case as
  28. *            |  parameter to be compatible with standard C functions
  29. *  7-Aug-86 | Fixed bug with default pitches and rests
  30. * 23-Oct-86 | JMaloney: Improved efficiency of note sorter by keeping
  31. *            |    hint pointers.
  32. *  4-Nov-86 | JMaloney: Changed memory allocator to avoid large per-node
  33. *            |    overhead of malloc.
  34. *  5-Nov-86 | JMaloney: Made scanint return long. Made durations and times
  35. *            |    unsigned longs because we were running out of bits in the
  36. *            |    duration calculations. Changed radix point to 1024 and
  37. *            |    reversedthe order of multiplying and dividing in rate and
  38. *            |    tempo calculations because of overflow danger. (We now do the
  39. *            |    divides *first*.) Put in error check for durations too large
  40. *            |    to be represented as a sixteen bit unsigned number.
  41. * 10-Nov-86 | JMaloney & RJoseph: Converted to LighspeedC
  42. *            |   Changed "line" to "lineBuff"
  43. *  4-Jan-87 | JMaloney: Get input from a stream
  44. * 11-Jan-87 | JMaloney: Fixed Rate scaling to apply to U and T commands
  45. *****************************************************************************/
  46.  
  47. #include "switches.h"
  48.  
  49. #ifdef LIGHTSPEED
  50. #include <StdIO.h>
  51. #include <CType.h>
  52. #include <MemoryMgr.h>
  53. #endif
  54.  
  55. #ifdef MPW
  56. #include <StdIO.h>
  57. #include <CType.h>
  58. #include <Types.h>
  59. #include <Memory.h>
  60. #endif
  61.  
  62. #include "cext.h"
  63. #include "adagio.h"
  64. #include "cmdline.h"
  65. #include "stream.h"
  66. #include "phase1.h"
  67. #include "phase2.h"
  68. #include "userio.h"
  69.  
  70. /****************************************************************************
  71. *
  72. *    constants, types, and macros
  73. *
  74. ****************************************************************************/
  75.  
  76. /* the following are used to simulate fixed point numbers with
  77.  *    the radix point 12 bits from the right: */
  78. #define precise(x) (((ulong) x) << 12)
  79. #define round(x) ((((ulong) x) + 2048L) >> 12)
  80. #define trunc(x) (((ulong) x) >> 12)
  81.  
  82. #define nullstring(s) ((s)[0] == '\0')
  83.  
  84. /* MAX_DUR is the maximum duration which may be represented by 16 bits
  85.  * NOTE: absolute times (vs. durations) are represented by 32 bits */
  86. #define MAX_DUR 0xFFFFL
  87.  
  88. /* this structure is used in allocating/freeing large chunks of
  89.  * memory; see event_alloc for details
  90.  */
  91. typedef struct mem_chunk {
  92.     struct mem_chunk *next;
  93. } *MemChunkPtr;
  94.  
  95. /* allocate this 2000 notes at a time */
  96. #define CHUNK_SIZE (2000L * sizeof(struct event_struct))
  97.  
  98. /****************************************************************************
  99. *
  100. *    routines private to this module
  101. *
  102. ****************************************************************************/
  103.  
  104. void        do_a_rest(void);
  105. void        doabsdur(void);
  106. void        doabspitch(void);
  107. void        docomment(void);
  108. void        doctrl(int);
  109. void        dodur(void);
  110. void        doerror(void);
  111. void        doloud(void);
  112. void        donextdur(void);
  113. void        dopitch(void);
  114. void        doprogram(void);
  115. void        dorate(void);
  116. void        dospecial(void);
  117. void        dotempo(void);
  118. void        dotime(void);
  119. void        dovoice(void);
  120. event_type    event_alloc(void);
  121. void        fferror(char *);
  122. void        init(void);
  123. boolean     ins_ctrl(event_type *);
  124. void        ins_event(event_type *, event_type);
  125. boolean     ins_note(event_type *);
  126. int            issymbol(void);
  127. void        marker(int);
  128. void        parseend(void);
  129. void        parsefield(void);
  130. boolean        parsenote(event_type *);
  131. ulong        parsesymdur(void);
  132. ulong        scaleby(ulong, ulong, boolean);
  133. int            scan(char *);
  134. ulong        scanint(void);
  135. int            scanterminator(char *);
  136.  
  137. /****************************************************************************
  138. *
  139. *    parser tables
  140. *
  141. ****************************************************************************/
  142.  
  143. /* symbol (keyword) table: */
  144. #define sym_n 3
  145. private char *ssymbols[sym_n] = {"RATE", "TEMPO", "ENDSCORE"};
  146. #define sym_rate 0
  147. #define sym_tempo 1
  148. #define sym_endscore 2
  149.  
  150. /* loudness translation table: */
  151. struct loudt {
  152.     char symbol[4];
  153.     int value;
  154. };
  155. struct loudt loudtable[] = {
  156.     "PPP", 20,
  157.     "PP\0", 26,
  158.     "P\0\0", 34,
  159.     "MP\0", 44,
  160.     "MF\0", 58,
  161.     "F\0\0", 75,
  162.     "FF\0", 98,
  163.     "FFF", 127
  164. };
  165.  
  166. private int pitchtable[7] = {57, 59, 48, 50, 52, 53, 55};
  167.  
  168. /****************************************************************************
  169. *
  170. *    variables private to this module
  171. *
  172. ****************************************************************************/
  173.  
  174. /* hints to optimize score sorting: */
  175. private event_type last_event = NULL;    /* last event inserted */
  176. private event_type ref_event = NULL;    /* last_event as of the most recent
  177.                                          *   !rate or !tempo directive */
  178. /* storage allocation bookkeeping: */
  179. private MemChunkPtr firstChunk = NULL;    /* first in chain of allocated chunks */
  180. private event_type eventPool = NULL;    /* next event to alloc */
  181. private ulong eventsInChunk = 0;        /* events left in this chunk */
  182.  
  183. /* misc: */
  184. private boolean debug = false;        /* controls verbose printout */
  185. private boolean endFlag = false;    /* set "true" when "!ENDSCORE" is seen */
  186. private ulong note_count = 0;        /* number of notes translated */
  187. private ulong ctrl_count = 0;        /* number of control commands translated */
  188.  
  189. /* input and lexical analysis variables: */
  190. #define LINE_SIZE 100
  191. private char lineBuff[LINE_SIZE];    /* the input line */
  192. private char token[LINE_SIZE];        /* a token from the input line */
  193. private int linex;            /* index of the next character to be scanned */
  194. private int fieldx;            /* index of the current character within a field */
  195.  
  196. private boolean ndurp;
  197.     /* set when the time for the next event (N) is indicated
  198.      * (next time defaults to the current time plus duration unless
  199.      *  overridden by a next (N) command whose presence is signalled
  200.      *  by ndurp)
  201.      * NOTE: this flag is NOT inherited by the next line */
  202.  
  203. private boolean pitch_flag;
  204.     /* set when a pitch is indicated
  205.      * (if controls changes are given, only allocate a note event if
  206.      *  a pitch was specified -- i.e. when pitch_flag is set)
  207.      * NOTE: this flag is NOT inherited by the next line */
  208.  
  209. private boolean rest_flag;
  210.     /* set when a rest (R) is indicated
  211.      * NOTE: this flag is NOT inherited by the next line */
  212.  
  213. /****************************************************************************
  214. *                state variables
  215. *
  216. * because each line of an Adagio score inherits properties from the previous
  217. * line, it makes sense to implement the parser as a collection of routines
  218. * that make small changes to some global state.     for example, pitch is a
  219. * global variable.  when the field G4 is encountered, the dopitch routine
  220. * assigns the pitch number for G4 to the variable pitch.  after all fields
  221. * are processed, these variables describe the current note and contain the
  222. * default parameters for the next note as well.
  223. *
  224. * global variables that are used in this way by the parsing rountines are:
  225. ****************************************************************************/
  226.  
  227. private boolean symbolic_dur_flag;
  228.     /* true if last dur was not absolute
  229.      * (if this is set, then the default duration is changed
  230.      *  accordingly when the tempo is changed) */
  231.  
  232. private boolean ctrlflag[nctrl];
  233.     /* ctrlflag[i] is set to indicate a control change for the ith controller
  234.      * the new value for the controller is in ctrlval[i]
  235.      * ctrlflag[0] is true if ANY control change was present */
  236.  
  237. private ushort ctrlval[nctrl];
  238.     /* the new value of each control that changed
  239.      * NOTE: the value of ctrlval[i] is only significant
  240.      *       if ctrlflag[i] is true */
  241.  
  242. private int
  243.     lineno,        /* current line number */
  244.     pitch,        /* pitch of note (may be negative) */
  245.     loud,        /* loudness of note */
  246.     voice,        /* voice (midi channel) of note */
  247.     program,    /* midi program (timbre control) of note */
  248.     last_prog;    /* saved value of program inherited from previous line
  249.                 /* (this is needed to implement the rule that note events
  250.                  *  are generated for rests if the program has changed) */
  251.  
  252. private ulong
  253.     dur,        /* the duration of the note */
  254.     ntime,        /* the starting time of the next note (ntime after this one) */
  255.     rate,        /* the current rate -- scales times and durations, unity = 100 */
  256.     tempo,        /* the current tempo */
  257.     thetime,    /* the current time; sets the starting time of the next note */
  258.     ref_time;    /* the time of the last !tempo or !rate command */
  259.  
  260. /****************************************************************************
  261. *                do_a_rest
  262. * Effect:
  263. *    parses a rest (R) command
  264. ****************************************************************************/
  265.  
  266. private void do_a_rest()
  267. {
  268.     if (fieldx < strlen(token))
  269.         fferror("Nothing expected after rest");
  270.     rest_flag = true;
  271. }
  272.  
  273. /****************************************************************************
  274. *                doabsdur
  275. * Effect:
  276. *    parses an absolute dur (U) command
  277. ****************************************************************************/
  278.  
  279. private void doabsdur()
  280. {
  281.     if (isdigit(token[fieldx])) {
  282.         dur = precise(scanint());
  283.         dur = scaleby(dur, rate, true);    /* scale by rate */
  284.         if (fieldx < strlen(token)) {
  285.             fferror("U must be followed by digits only");
  286.         }
  287.         symbolic_dur_flag = false;
  288.     } else {
  289.         fferror("No digit after U");
  290.     }
  291. }
  292.  
  293. /****************************************************************************
  294. *                doabspitch
  295. * Effect:
  296. *    parses an absolute pitch (P) command
  297. ****************************************************************************/
  298.  
  299. private void doabspitch()
  300. {
  301.     if (isdigit (token[fieldx])) {
  302.         pitch = (ushort) scanint();
  303.         pitch_flag = true;
  304.         if (fieldx < strlen(token)) {
  305.             fferror("P must be followed by digits only");
  306.         } else if (pitch < minpitch) {
  307.             fieldx = 1;
  308.             fferror("Minimum pitch of -12 will be used");
  309.             pitch = minpitch;
  310.         } else if (pitch > maxpitch) {
  311.             fieldx = 1;
  312.             fferror("Maximum pitch of 115 will be used");
  313.             pitch = maxpitch;
  314.         }
  315.     } else {
  316.         fferror("No digits after P");
  317.     }
  318. }
  319.  
  320. /****************************************************************************
  321. *                docomment
  322. * Effect:
  323. *    parses a comment (*) command
  324. ****************************************************************************/
  325.  
  326. private void docomment()
  327. {
  328.     lineBuff[linex] = '\0'; /* force end of line to skip comment line */
  329. }
  330.  
  331. /****************************************************************************
  332. *                doctrl
  333. * Inputs:
  334. *    int n: control number
  335. * Effect:
  336. *    parses a control (J, K, M, O, X, or Y) command
  337. ****************************************************************************/
  338.  
  339. private void doctrl(n)
  340.     int n;
  341. {
  342.     ctrlval[n] = (ushort) scanint();
  343.     if (fieldx < strlen(token)) {
  344.         fferror("Only digits expected here");
  345.     } else {
  346.         ctrlflag[n] = true;
  347.         ctrlflag[0] = true;    /* ctrlflag[0] set if any flag is set */
  348.     }
  349. }
  350.  
  351. /****************************************************************************
  352. *                dodur
  353. * Effect:
  354. *    parses a duration (S, I, Q, H, or W) command
  355. ****************************************************************************/
  356.  
  357. private void dodur()
  358. {
  359.     /* symbolic: scale by rate AND tempo: */
  360.     dur = parsesymdur();
  361.     dur = scaleby(dur, ((tempo * rate) / 100L), true);
  362.     symbolic_dur_flag = true;
  363. }
  364.  
  365. /****************************************************************************
  366. *                doerror
  367. * Effect:
  368. *    parse an unrecognized field by reporting an error
  369. ****************************************************************************/
  370.  
  371. private void doerror()
  372. {
  373.     fieldx = 0;
  374.     fferror("Bad field");
  375. }
  376.  
  377. /****************************************************************************
  378. *                doloud
  379. * Effect:
  380. *    parse a loudness (L) command
  381. ****************************************************************************/
  382.  
  383. private void doloud()
  384. {
  385.     int i, j;
  386.  
  387.     if (strlen(token) < 2) {
  388.         fieldx = 0;
  389.         fferror("L must be followed by loudness indication");
  390.         return;
  391.     }
  392.  
  393.     if (isdigit(token[fieldx])) {
  394.         loud = (ushort) scanint();
  395.         if (fieldx < strlen(token)) {
  396.             fferror("Digits expected after L");
  397.         } else if (loud > 127) {
  398.             fieldx = 1;
  399.             fferror("Maximum loudness of 127 will be used");
  400.             loud = 127;
  401.         }
  402.         return;
  403.     }
  404.  
  405.     if (strlen(token) > 4 ) {    /* maximum is 4, e.g. "Lppp" */
  406.         fieldx = 0;
  407.         fferror("Loudness field too long");
  408.         return;
  409.     }
  410.  
  411.     if (strlen(token) != 4) {    /* pad short symbols with 0    */
  412.         i = strlen(token);        /* e.g. "p\0" -> "p\0\0"    */
  413.         token[i+1] = '\0';
  414.     }
  415.  
  416.     for (i = 0; i <= 7; i++) {    /* loop through possibilities */
  417.         for (j = 0; j <= 2; j++) {    /* test 3 characters */
  418.             if (token[fieldx+j] != loudtable[i].symbol[j])
  419.                 break;
  420.         }
  421.         if (j == 3) {
  422.             loud = loudtable[i].value;
  423.             return;
  424.         }
  425.     }
  426.  
  427.     fieldx = 1;
  428.     fferror("Bad loudness indication");
  429. }
  430.  
  431. /****************************************************************************
  432. *                donextdur
  433. * Effect:
  434. *    parse a next (N) command
  435. ****************************************************************************/
  436.  
  437. private void donextdur()
  438. {
  439.     if (isdigit(token[fieldx])) {
  440.         ntime = precise(scanint());
  441.         ntime = scaleby(ntime, rate, false);    /* scale by rate */
  442.         if (fieldx < strlen(token))
  443.             fferror("Only digits expected here");
  444.     } else {
  445.         /* symbolic: scale by rate AND tempo: */
  446.         ntime = parsesymdur();
  447.         ntime = scaleby(ntime, ((tempo * rate) / 100L), false);
  448.     }
  449.     ndurp = true;    /* flag that N was given */
  450. }
  451.  
  452. /****************************************************************************
  453. *                dopitch
  454. * Effect:
  455. *    parses a pitch command
  456. ****************************************************************************/
  457.  
  458. private void dopitch()
  459. {
  460.     int p;
  461.     ushort octave;
  462.     boolean octflag = false;    /* set true if octave is specified */
  463.  
  464.     p = pitchtable[token[0] - 'A'];
  465.     for (;;) {
  466.         if (token[fieldx] == 'S') {                /* sharp */
  467.             p++;
  468.             fieldx++;
  469.         } else if (token[fieldx] == 'F') {        /* flat */
  470.             p--;
  471.             fieldx++;
  472.         } else if (token[fieldx] == 'N') {        /* natural */
  473.             fieldx++;
  474.         } else if (isdigit(token[fieldx]) && !octflag) {
  475.             octave = (ushort) scanint();        /* octave */
  476.             octflag = true;
  477.         } else break;                            /* none of the above */
  478.     }
  479.  
  480.     if (octflag) {
  481.         /* adjust p to given octave */
  482.         p = (p - 48) + (12 * octave);
  483.     } else {
  484.         /* adjust p to note nearest the default pitch */
  485.         int octdiff = (p + 126 - pitch) / 12;
  486.         p = p + 120 - (octdiff * 12);
  487.     }
  488.  
  489.     if (fieldx < strlen(token))        /* any unparsed characters? */
  490.         fferror("Bad pitch indication");
  491.  
  492.     if (p > maxpitch) {                /* pitch in range? */
  493.         fieldx = 1;
  494.         fferror("Pitch too high");
  495.         p = maxpitch;
  496.     }
  497.  
  498.     pitch = p;
  499.     pitch_flag = true;
  500. }
  501.  
  502. /****************************************************************************
  503. *                doprogram
  504. * Effect:
  505. *    parses a program change (Z) command
  506. ****************************************************************************/
  507.  
  508. private void doprogram()
  509. {
  510.     if (isdigit(token[fieldx])) {
  511.         program = (ushort) scanint();
  512.         if (fieldx < strlen(token)) {
  513.             fferror("Z must be followed by digits only");
  514.         } else if (program < minprogram) {
  515.             fieldx = 1;
  516.             fferror("Minimum program of 1 will be used");
  517.             program = minprogram;
  518.         } else if (program > maxprogram) {
  519.             fieldx = 1;
  520.             fferror("Maximum program of 128 will be used");
  521.             program = maxprogram;
  522.         }
  523.     } else {
  524.         fferror("No digit after Z");
  525.     }
  526. }
  527.  
  528. /****************************************************************************
  529. *                dorate
  530. * Effect:
  531. *    parses a !rate command
  532. ****************************************************************************/
  533.  
  534. private void dorate()
  535. {
  536.     linex += scan(&lineBuff[linex]);
  537.  
  538.     if (nullstring(token))
  539.         fferror("rate number expected");
  540.     else {
  541.         ulong oldrate = rate;    /* save current rate */
  542.  
  543.         fieldx = 0;
  544.         rate = scanint();
  545.         if (fieldx < strlen(token))
  546.             fferror("Only digits expected here");
  547.  
  548.         if (rate == 0) {
  549.             fieldx = 0;
  550.             fferror("Rate 100 will be used here");
  551.             rate = 100;
  552.         }
  553.  
  554.         ref_time = thetime;        /* remember event list hint */
  555.         ref_event = last_event;
  556.  
  557.         /* adjust dur in case it is inherited by next note */
  558.         dur = (dur / rate) * oldrate;
  559.     }
  560. }
  561.  
  562. /****************************************************************************
  563. *                dospecial
  564. * Effect:
  565. *    parses special (those starting with "!") commands
  566. ****************************************************************************/
  567.  
  568. private void dospecial()
  569. {
  570.     switch (issymbol()) {
  571.     case sym_rate:
  572.         dorate();
  573.         break;
  574.     case sym_tempo:
  575.         dotempo();
  576.         break;
  577.     case sym_endscore:
  578.         endFlag = true;
  579.         break;
  580.     default:
  581.         fferror("Special command expected");
  582.     }
  583.     parseend(); /* flush the rest of the line */
  584. }
  585.  
  586. /****************************************************************************
  587. *                dotempo
  588. * Effect:
  589. *    parses a !tempo command
  590. ****************************************************************************/
  591.  
  592. private void dotempo()
  593. {
  594.     linex += scan(&lineBuff[linex]);
  595.  
  596.     if (nullstring(token)) {
  597.         fferror("Tempo number expected");
  598.     } else {
  599.         ulong oldtempo = tempo;    /* save current tempo */
  600.  
  601.         fieldx = 0;
  602.         tempo = scanint();
  603.         if (fieldx < strlen(token))
  604.             fferror("Only digits expected here");
  605.  
  606.         if (tempo == 0) {
  607.             fieldx = 0;
  608.             fferror("Tempo 100 will be used here");
  609.             tempo = 100;
  610.         }
  611.  
  612.         ref_time = thetime;
  613.         ref_event = last_event;    /* remember event list hint */
  614.  
  615.         /* adjust dur in case it is inherited by next note */
  616.         if (symbolic_dur_flag) {
  617.             dur = (dur / tempo) * oldtempo;
  618.         }
  619.     }
  620. }
  621.  
  622. /****************************************************************************
  623. *                dotime
  624. * Effect:
  625. *    parses a time (T) command
  626. ****************************************************************************/
  627.  
  628. private void dotime()
  629. {
  630.     if (isdigit(token[fieldx])) {
  631.         thetime = precise(scanint());
  632.         thetime = scaleby(thetime, rate, false);    /* scale by rate */
  633.         if (fieldx < strlen(token))
  634.             fferror("Only digits expected here");
  635.     } else {
  636.         /* symbolic: scale by rate AND tempo: */
  637.         thetime = parsesymdur();
  638.         thetime = scaleby(thetime, ((tempo * rate) / 100L), false);
  639.     }
  640.     thetime += ref_time;    /* time is relative to the reference time */
  641. }
  642.  
  643. /****************************************************************************
  644. *                dovoice
  645. * Effect:
  646. *    parse a voice (V) command (the voice is the MIDI channel)
  647. ****************************************************************************/
  648.  
  649. private void dovoice()
  650. {
  651.     if (isdigit(token[fieldx])) {
  652.         voice = (ushort) scanint();
  653.         if (fieldx < strlen(token))
  654.             fferror("V must be followed by digits only");
  655.         if (voice > 16) {
  656.             fferror("number too high, using 16 instead");
  657.             voice = 16;
  658.         } else if (voice < 1) {
  659.             fferror("number too low, using 1 instead");
  660.             voice = 1;
  661.         }
  662.     } else {
  663.         fferror("No digit after V");
  664.     }
  665. }
  666.  
  667. /****************************************************************************
  668. *                event_alloc
  669. * Returns:
  670. *    event_type: a new event structure or
  671. *                NULL if there is not enough memory left
  672. * Effect:
  673. *    allocates memory from the heap as needed
  674. * Implementation:
  675. *    to reduce the per block storage overhead, we allocate memory in
  676. *    large chunks and do our own allocation
  677. * WARNING: this implementation assumes that individual events are never freed!!
  678. ****************************************************************************/
  679.  
  680. private event_type event_alloc()
  681. {
  682.     ulong biggestChunk, junk, allocSize;
  683.     MemChunkPtr newChunk;
  684.  
  685.     if (eventsInChunk <= 0) {
  686.         biggestChunk = MaxMem(&junk);
  687.         if (biggestChunk <= (SPACE_FOR_PLAY + sizeof(struct mem_chunk))) {
  688.             gprintf(FATAL,
  689.                     "Out of memory in phase1, space = %ld.", biggestChunk);
  690.             clean_exit();
  691.         }
  692.         allocSize =
  693.             (biggestChunk > (SPACE_FOR_PLAY + CHUNK_SIZE)) ?
  694.                 CHUNK_SIZE :
  695.                 (biggestChunk - SPACE_FOR_PLAY);
  696.             /* take CHUNK_SIZE or largest fraction thereof which
  697.              * still leaves SPACE_FOR_PLAY bytes of contiguous storage */
  698.         newChunk = (MemChunkPtr) NewPtr(allocSize);
  699.         if (newChunk == NULL) {
  700.             /* should never happen */
  701.             gprintf(FATAL,
  702.                 "Implementation error (phase1.c): memory allocation.");
  703.             clean_exit();
  704.         }
  705.  
  706.         /* add newChunk to chunk chain */
  707.         newChunk->next = firstChunk;
  708.         firstChunk = newChunk;
  709.  
  710.         /* make newChunk into new eventPool */
  711.         eventPool = (event_type) (newChunk + 1);
  712.         eventsInChunk =
  713.             (allocSize - sizeof(struct mem_chunk)) /
  714.                 sizeof(struct event_struct);
  715.     }
  716.     eventsInChunk--;
  717.     return eventPool++;
  718. }
  719.  
  720. /****************************************************************************
  721. *                fferror
  722. * Inputs:
  723. *    char * s: an error message string
  724. * Effect:
  725. *    prints the line with the error
  726. *    puts a cursor (^) at the error location
  727. *    prints the error message (s)
  728. * Implementation:
  729. *    this routine prints a carat under the character that
  730. *    was copied into token[fieldx].    for example, if fieldx = 0, the
  731. *    carat will point to the first character in the field.
  732. ****************************************************************************/
  733.  
  734. private void fferror(s)
  735.     char *s;
  736. {
  737.     gprintf(TRANS, "%5d | %s\n", lineno, lineBuff);
  738.     marker(linex - strlen(token) + fieldx + 8);
  739.     gprintf(TRANS, "Error: %s.\n", s);
  740. }
  741.  
  742. /****************************************************************************
  743. *                phase1_FreeMem
  744. * Effect:
  745. *    frees storage occupied by all scores created since initialization or
  746. *    the last call to FreeMem()
  747. ****************************************************************************/
  748.  
  749. public void phase1_FreeMem()
  750. {
  751.     MemChunkPtr nextChunk = firstChunk;
  752.     MemChunkPtr temp;
  753.  
  754.     while (nextChunk != NULL) {
  755.         temp = nextChunk->next;
  756.         DisposPtr(nextChunk);
  757.         nextChunk = temp;
  758.     }
  759.     firstChunk = NULL;
  760.     eventPool = NULL;
  761.     eventsInChunk = 0;
  762. }
  763.  
  764. /****************************************************************************
  765. *                init
  766. * Effect:
  767. *    initializes the state variables
  768. ****************************************************************************/
  769.  
  770. private void init()
  771. {
  772.     int i;
  773.  
  774.     endFlag = false;
  775.     note_count = 0;
  776.     ctrl_count = 0;
  777.     last_event = NULL;
  778.     ref_event = NULL;
  779.     firstChunk = NULL;
  780.     eventPool = NULL;
  781.     eventsInChunk = 0;
  782.  
  783.     /* initial (default) values for all state variables */
  784.     symbolic_dur_flag = true; /* default dur is symbolic */
  785.     for (i = 0; i < nctrl; i++) {
  786.         /* no initial control changes */
  787.         ctrlflag[i] = false;
  788.         ctrlval[i] = 0;
  789.     }
  790.  
  791.     lineno = 0;
  792.     pitch = 48;    /* middle C */
  793.     loud = 127;
  794.     voice = 1;
  795.     program = 1;
  796.     last_prog = 1;
  797.     tempo = 100;
  798.     rate = 100;
  799.     dur = precise((ulong) 60); /* default dur is quarter note */
  800.     thetime = 0;
  801.     ref_time = 0;
  802.     ntime = 0;
  803. }
  804.  
  805. /****************************************************************************
  806. *                ins_ctrl
  807. * Inputs:
  808. *    event_type * scorePtr: a pointer to the head of a linked list
  809. *                           in which to insert the control event
  810. * Returns:
  811. *    boolean: true on success, false if not enough memory
  812. * Effect:
  813. *    control events corresponding to current line are inserted in *scorePtr
  814. * Implementation:
  815. *    ctrlflag[i] is true if control i was specified in this line, so
  816. *    insert one control change for each ctrlflag[i] that is true
  817. ****************************************************************************/
  818.  
  819. private boolean ins_ctrl(scorePtr)
  820.     event_type *scorePtr;
  821. {
  822.     int i;
  823.     event_type ctrl;
  824.  
  825.     for (i = 1; i < nctrl; i++) {
  826.         if (ctrlflag[i]) {
  827.             ctrl_count++;
  828.             if ((ctrl = event_alloc()) == NULL) {
  829.                 return false;    /* out of memory */
  830.             } else {
  831.                 ctrl->ntime = round(thetime);
  832.                 ctrl->nline = lineno;
  833.                 ctrl->nvoice = voice;
  834.                 ctrl->ncontroller = i;
  835.                 ctrl->u.ctrl.value = ctrlval[i];
  836.                 ctrl->next = NULL;
  837.                 ins_event(scorePtr, ctrl);
  838.             }
  839.             ctrlflag[i] = false;
  840.             ctrlval[i] = 0;
  841.         }
  842.     }
  843.     return true;    /* success! */
  844. }
  845.  
  846. /****************************************************************************
  847. *                ins_event
  848. * Inputs:
  849. *    event_type * listHeadPtr: a pointer to the head of
  850. *                              the linked list in which to insert the event
  851. *    event_type event: the event to insert
  852. * Effect:
  853. *    inserts event into the event list
  854. *    NOTE: it is inserted *after* previously inserted events with the same time
  855. * Implementation:
  856. *    adagio files often contain many independent voices.  although each voice
  857. *    consists of events in sequence, the voices are not inter-twined in the
  858. *    adagio file.  rather, all the events of voice 1 appear followed by all
  859. *    the events of voice 2, and so forth.  as phase one merges these event
  860. *    sequences, it must make many passes over an increasingly long list of
  861. *    events: expensive if we always start from the beginning of the list!
  862. *    we can exploit the fact that each voice is sequential by starting the
  863. *    search for the proper point of insertion at the last event inserted.
  864. *    the variable "last_event" is used to remember this hint.  we
  865. *    also snapshot "last_event" in "ref_event" when a !tempo or !rate
  866. *    command occurs as another hint.
  867. ****************************************************************************/
  868.  
  869. private void ins_event(listHeadPtr, event)
  870.     event_type *listHeadPtr;
  871.     register event_type event;
  872. {
  873.     if ((*listHeadPtr == NULL) || (event->ntime < (*listHeadPtr)->ntime)) {
  874.         /* insert at the head of the list */
  875.         event->next = *listHeadPtr;
  876.         *listHeadPtr = event;
  877.         ref_event = last_event = event;
  878.     } else {
  879.         /* insert somewhere after the head of the list
  880.     \     * assume: last_event and ref_event are not NULL.  why?  because they
  881.          * are only null before the first insertion, which is taken
  882.          * care of in the previous arm of this conditional. */
  883.  
  884.         register event_type previous;
  885.         register event_type insert_before;
  886.  
  887.         if (event->ntime >= last_event->ntime) {
  888.             /* insertion point is after last_event */
  889.             previous = last_event;
  890.             insert_before = last_event->next;
  891.         } else if (event->ntime >= ref_event->ntime) {
  892.             /* insertion point is after ref_event */
  893.             previous = ref_event;
  894.             insert_before = ref_event->next;
  895.         } else {
  896.             /* insertion point is before last_event; start at beginning */
  897.             /* assume: not inserting at very head of list; that would
  898.              * have been taken care of above */
  899.              previous = *listHeadPtr;
  900.             insert_before = previous->next;
  901.         }
  902.  
  903.         while ((insert_before != NULL) &&
  904.                (event->ntime >= insert_before->ntime)) {
  905.             previous = insert_before;
  906.             insert_before = insert_before->next;
  907.         }
  908.         previous->next = event;
  909.         event->next = insert_before;
  910.         last_event = event;
  911.     }
  912. }
  913.  
  914. /****************************************************************************
  915. *                ins_note
  916. * Inputs:
  917. *    event_type * score: a pointer to the head of the linked list
  918. *                        in which to insert the note
  919. * Returns:
  920. *    boolean: true on success, false if not enough memory
  921. * Effect:
  922. *    note events (if any) corresponding to the current line are inserted in score
  923. * Implementation:
  924. *    if a note on should occur after a note off and doesn't, and the
  925. *    two notes have the same pitch, then the note off can cancel the
  926. *    note on.  to make it unlikely that roundoff will cause this situation,
  927. *    dur is decreased by one half of a clock tick before rounding.
  928. *    also, phase2 gives precedence to note-offs that are simultaneous
  929. *    with note-ons.
  930. ****************************************************************************/
  931.  
  932. private boolean ins_note(score)
  933.     event_type *score;
  934. {
  935.     event_type note;
  936.  
  937.     note_count++;
  938.     if ((note = event_alloc()) == NULL) {
  939.         return false;    /* out of memory */
  940.     } else {
  941.         note->ntime = round(thetime);
  942.         note->nline = lineno;
  943.         note->nvoice = voice;
  944.         note->ncontroller = 0;    /* this is a note */
  945.         note->u.note.ndur = (ushort) trunc(dur);
  946.         if (rest_flag) {
  947.             note->u.note.npitch = NO_PITCH;    /* a rest */
  948.         } else {
  949.             note->u.note.npitch = pitch;
  950.         }
  951.         note->u.note.nloud = loud;
  952.         note->u.note.nprogram = program;
  953.         if (debug) {
  954.             gprintf(TRANS,
  955.                 "note: time %ld, dur %d, pitch %d, voice %d, loudness %d\n",
  956.                 note->ntime, note->u.note.ndur, note->u.note.npitch,
  957.                 note->nvoice, note->u.note.nloud);
  958.         }
  959.         note->next = NULL;
  960.         ins_event(score, note);
  961.     }
  962.     return true;    /* success! */
  963. }
  964.  
  965. /****************************************************************************
  966. *                issymbol
  967. * Returns:
  968. *    int: symbol number, or -1 if no match
  969. * Assumes:
  970. *    token[1] has the symbol to look up (token[0] == '!')
  971. ****************************************************************************/
  972.  
  973. private int issymbol()
  974. {
  975.     register int symb_num;
  976.     register char *symPtr;
  977.     register char *tokenPtr;
  978.  
  979.     for (symb_num = 0; symb_num < sym_n; symb_num++) {
  980.         tokenPtr = &token[1];
  981.         symPtr = ssymbols[symb_num];
  982.         for (;;) {
  983.             if ((*tokenPtr == '\0') && (*symPtr == '\0')) return symb_num;
  984.             if (*tokenPtr++ != *symPtr++) break;
  985.         }
  986.     }
  987.     return -1;
  988. }
  989.  
  990. /****************************************************************************
  991. *                marker
  992. * Inputs:
  993. *    int count: the number of characters to indent
  994. * Effect:
  995. *    prints a carat (^) at the position specified on file stderr
  996. ****************************************************************************/
  997.  
  998. private void marker(count)
  999.     int count;
  1000. {
  1001.     int i;
  1002.     char temp[LINE_SIZE];
  1003.  
  1004.     for (i = 0; i < count; i++) {
  1005.         temp[i] = ' ';
  1006.     }
  1007.     temp[i] = '\0';
  1008.     gprintf(TRANS, "%s^\n", temp);
  1009. }
  1010.  
  1011. /*****************************************************************
  1012. *            parseend
  1013. * Effect:
  1014. *    parse the note terminator, either ",", ";", "\0", or "\n"
  1015. ****************************************************************/
  1016.  
  1017. private void parseend()
  1018. {
  1019.     linex += scanterminator(&lineBuff[linex]);
  1020.     switch (token[0]) {
  1021.         case ',':
  1022.             ndurp = true;    /* flag that next time was specified */
  1023.             ntime = 0;
  1024.             break;
  1025.         case ';':
  1026.         case '\0':
  1027.         case '\n':
  1028.             break;
  1029.         default:
  1030.             fferror("Internal error: illegal separator?");
  1031.             break;
  1032.     }
  1033. }
  1034.  
  1035. /****************************************************************************
  1036. *                parsefield
  1037. * Effect:
  1038. *    looks at first character of token and calls a parsing routine
  1039. ****************************************************************************/
  1040.  
  1041. private void parsefield()
  1042. {
  1043.     fieldx = 1;
  1044.     switch (token[0]) {
  1045.         case 'T': dotime(); break;
  1046.         case 'W':
  1047.         case 'H':
  1048.         case 'Q':
  1049.         case 'I':
  1050.         case 'S': fieldx = 0; dodur(); break;
  1051.         case 'R': do_a_rest(); break;
  1052.         case 'A':
  1053.         case 'B':
  1054.         case 'C':
  1055.         case 'D':
  1056.         case 'E':
  1057.         case 'F':
  1058.         case 'G': dopitch(); break;
  1059.         case 'P': doabspitch (); break;
  1060.         case 'U': doabsdur(); break;
  1061.         case 'L': doloud(); break;
  1062.         case 'N': donextdur(); break;
  1063.         case 'J': doctrl(1); break;
  1064.         case 'K': doctrl(2); break;
  1065.         case 'M': doctrl(3); break;
  1066.         case 'O': doctrl(4); break;
  1067.         case 'X': doctrl(5); break;
  1068.         case 'Y': doctrl(6); break;
  1069.         case 'V': dovoice(); break;
  1070.         case 'Z': doprogram(); break;
  1071.         default : doerror(); break;
  1072.     }
  1073. }
  1074.  
  1075. /****************************************************************************
  1076. *                parsenote
  1077. * Inputs:
  1078. *    event_type * scorePtr: pointer to base of the note list
  1079. * Effect:
  1080. *    parses a note line and inserts note and/or control events (if any)
  1081. *    into *scorePtr
  1082. * Assumes:
  1083. *    line contains a string to be parsed
  1084. ****************************************************************************/
  1085.  
  1086. private boolean parsenote(scorePtr)
  1087.     event_type *scorePtr;
  1088. {
  1089.     boolean out_of_memory = false;
  1090.  
  1091.     /* reset the per-note flags */
  1092.     ndurp = false;
  1093.     pitch_flag = false;
  1094.     rest_flag = false;
  1095.     ctrlflag[0] = false;
  1096.  
  1097.     /* this loop reads tokens for a note */
  1098.     while (!nullstring(token)) {
  1099.         parsefield();
  1100.         linex += scan(&lineBuff[linex]);
  1101.     }
  1102.     parseend(); /* take care of note terminator */
  1103.  
  1104.     /* insert ctrl's first so that they precede the note they effect */
  1105.     if (ctrlflag[0]) out_of_memory |= !ins_ctrl(scorePtr);
  1106.         /* don't reset ctrlflag[0] here; it is examined below */
  1107.  
  1108.     /* insert a note if
  1109.      *    (1) a pitch was specified OR
  1110.      *    (2) no control was specified and this is not a rest
  1111.      *        (it's a pitch by default) OR
  1112.      *    (3) there is a program change (even if this is a rest)
  1113.      *
  1114.      * NOTE: program changes during rests are advised since
  1115.      *    synthesizers may not be able to process a program
  1116.      *    change followed immediately by a note-on.  in fact, this
  1117.      *    is why we insert notes whose pitch is NO_PITCH -- so that
  1118.      *    the program change can be processed during the rest.
  1119.      */
  1120.     if (pitch_flag ||
  1121.         (!ctrlflag[0] && !rest_flag) ||
  1122.         (program != last_prog)) {
  1123.             out_of_memory = !ins_note(scorePtr);
  1124.             last_prog = program;
  1125.     }
  1126.  
  1127.     if (ndurp) thetime += ntime;
  1128.     else thetime += dur;
  1129.  
  1130.     return out_of_memory;
  1131. }
  1132.  
  1133. /*****************************************************************
  1134. *            parsesymdur
  1135. * Effect:
  1136. *    parse and return an unscaled symbolic duration
  1137. ****************************************************************/
  1138.  
  1139. private ulong parsesymdur()
  1140. {
  1141.     register ulong symdur;
  1142.     register ulong dotfactor;
  1143.  
  1144.     switch (token[fieldx]) {
  1145.     case 'W': symdur = precise(240L); break;
  1146.     case 'H': symdur = precise(120L); break;
  1147.     case 'Q': symdur = precise(60L);  break;
  1148.     case 'I': symdur = precise(30L);  break;
  1149.     case 'S': symdur = precise(15L);  break;
  1150.     default:
  1151.         fferror("Duration expected: one of W, H, Q, I, or S");
  1152.         return;
  1153.     }
  1154.  
  1155.     fieldx++;
  1156.     dotfactor = 1;
  1157.     for (;;) {
  1158.         register byte c = token[fieldx];
  1159.  
  1160.         if (c == '.') {                        /* dotted notation */
  1161.             dotfactor = dotfactor * 2;
  1162.             fieldx++;
  1163.         } else if (c == 'T') {                /* triplet notation */
  1164.             symdur = (symdur * 2) / 3;
  1165.             fieldx++;
  1166.         } else if (isdigit(c)) {            /* numbers are multipliers */
  1167.             symdur *= scanint();
  1168.         } else {
  1169.             break;                            /* exit this loop */
  1170.         }
  1171.     }
  1172.  
  1173.     if (fieldx < strlen(token)) {    /* any unparsed characters? */
  1174.         fferror("Bad duration");
  1175.         fieldx = strlen(token) + 1;
  1176.     }
  1177.  
  1178.     return  (symdur * 2) - (symdur / dotfactor);
  1179. }
  1180.  
  1181. /****************************************************************************
  1182. *                phase1_Parse
  1183. * Inputs:
  1184. *    StreamPtr inStream: input stream
  1185. * Returns:
  1186. *    event_type: the parsed score
  1187. *    ulong *notes: set to number of notes parsed
  1188. *    ulong *controls: set to number of control events parsed
  1189. * Effect:
  1190. *    parses score from inStream and builds a score data structure
  1191. ****************************************************************************/
  1192.  
  1193. public event_type phase1_Parse(inStream, notes, controls)
  1194.     StreamPtr inStream;
  1195.     ulong *notes;
  1196.     ulong *controls;
  1197. {
  1198.     event_type score = NULL;
  1199.     boolean out_of_memory = false;    /* set when out of memory */
  1200.  
  1201.  
  1202. #ifndef APPLICATION
  1203.     debug = cl_switch("-print");
  1204. #endif
  1205.  
  1206.     init();
  1207.  
  1208.     /* this loop reads lines */
  1209.     while (stream_GetLine(inStream, lineBuff, LINE_SIZE) &&
  1210.            (!out_of_memory) && (!endFlag)) {
  1211.         lineno++;
  1212.         linex = 0;
  1213.         /* this loop reads notes from a line */
  1214.         while ((lineBuff[linex] != '\0') &&
  1215.                (!out_of_memory) && (!endFlag)) {
  1216.             /* loop invariant: lineBuff[linex] is first char of next note */
  1217.             linex += scan(&lineBuff[linex]);
  1218.             if (!nullstring(token)) {
  1219.                 if (token[0] == '*') {
  1220.                     docomment();
  1221.                 } else if (token[0] == '!') {
  1222.                     dospecial();
  1223.                 } else {
  1224.                     out_of_memory = parsenote(&score);
  1225.                 }
  1226.             } else {
  1227.                 parseend();
  1228.             }
  1229.         }
  1230.     }
  1231.  
  1232.     if (out_of_memory) {
  1233.         gprintf(ERROR, "Out of note memory at line %ld;\n", lineno - 1);
  1234.         gprintf(ERROR, "  the rest of your file will be ignored.\n");
  1235.     }
  1236.  
  1237.     *notes = note_count;
  1238.     *controls = ctrl_count;
  1239.     return score;
  1240. }
  1241.  
  1242. /****************************************************************************
  1243. *                scaleby
  1244. * Inputs:
  1245. *    ulong raw: duration or time to scale
  1246. *    ulong factor: scale factor (tempo or rate)
  1247. *    boolean isDur: true to check duration bounds
  1248. * Returns:
  1249. *    ulong: the raw duration or time scaled by the scale factor
  1250. * Effect:
  1251. *    the duration or time is scaled by factor
  1252. *    if isDur is true then the result is checked to see if it will
  1253. *    fit into a 16-bit word
  1254. * Implementation:
  1255. *    factor is taken to be a rate where 100 is unity (i.e. no scaling),
  1256. *    50 is half-speed, 200 is double speed, etc
  1257. *    the division is done first to avoid overflow, which is especially
  1258. *    a possibility when scaling large time values
  1259. ****************************************************************************/
  1260.  
  1261. private ulong scaleby(raw, factor, isDur)
  1262.     ulong raw;
  1263.     ulong factor;
  1264.     boolean isDur;
  1265. {
  1266.     register ulong scaled = (raw / factor) * 100L;
  1267.  
  1268.     if (isDur && (scaled > precise(MAX_DUR))) {
  1269.         fferror("Duration too large to represent with 16 bits");
  1270.         scaled = precise(MAX_DUR);
  1271.     }
  1272.     return scaled;
  1273. }
  1274.  
  1275. /****************************************************************************
  1276. *                scan
  1277. * Inputs:
  1278. *    char * start: the string to scan
  1279. * Returns:
  1280. *    int: the number of characters consumed
  1281. * Effect:
  1282. *    skips over leading blanks and tabs
  1283. *    copies characters from start into token, converting to upper case
  1284. *    scanning stops on a delimiter, which is one of:
  1285. *      {space, tab, newline, null, comma, semicolon}
  1286. * Assumes:
  1287. *    there will be enough room in 'token' to hold the token read
  1288. ****************************************************************************/
  1289.  
  1290. private int scan(start)
  1291.     char *start;
  1292. {
  1293.     register char *src = start;
  1294.     register char *dest = token;
  1295.     register char c;
  1296.  
  1297.     while ((*src == ' ') || (*src == '\t'))
  1298.         src++;    /* skip spaces and tabs */
  1299.  
  1300.     while (((c = *src) != ' ') &&
  1301.             (c != '\0') &&
  1302.             (c != '\t') &&
  1303.             (c != '\n') &&
  1304.             (c != ',') &&
  1305.             (c != ';')) {
  1306.         *dest++ = toupper(*src++);
  1307.     }
  1308.     *dest = '\0';
  1309.     return (src - start);
  1310. }
  1311.  
  1312. /****************************************************************************
  1313. *                scanterminator
  1314. * Inputs:
  1315. *    char * start: the string to scan
  1316. * Returns:
  1317. *    int: the number of characters consumed
  1318. * Effect:
  1319. *    copies a terminator character from start into token
  1320. *    skips white space before terminator
  1321. ****************************************************************************/
  1322.  
  1323. private int scanterminator(start)
  1324.     register char *start;
  1325. {
  1326.     register char *src = start;
  1327.     register char *dst = &token[0];
  1328.  
  1329.     while ((*src == ' ') || (*src == '\t'))
  1330.         src++;    /* skip spaces and tabs */
  1331.  
  1332.     if ((*dst++ = toupper(*src)) != '\0') {
  1333.         *dst = '\0';
  1334.         src++;
  1335.     }
  1336.     return (src - start);
  1337. }
  1338.  
  1339. /****************************************************************************
  1340. *                scanint
  1341. * Returns:
  1342. *    ulong: the scanned integer
  1343. * Effect:
  1344. *    scans an unsigned integer from token, starting at fieldx
  1345. *    fieldx is incremented to end of the integer
  1346. ****************************************************************************/
  1347.  
  1348. private ulong scanint()
  1349. {
  1350.     register int tokenLength = strlen(token);
  1351.     register char c;
  1352.     register ulong num = 0;
  1353.  
  1354.     while (fieldx < tokenLength) {
  1355.         c = token[fieldx];
  1356.         if ((c >= '0') && (c <= '9')) {
  1357.             num = (num * 10) + (c - '0');
  1358.             fieldx++;
  1359.         } else {
  1360.             break;
  1361.         }
  1362.     }
  1363.     return num;
  1364. }
  1365.